<template>
  <div class="maintorPage" id="maintorPage">
    <header class="header">
      <div class="back" @click="back"><img src="~@/assets/monitor/back.png" alt="" />&ensp;返回</div>
      <div class="time"><img src="~@/assets/monitor/clock.png" alt="" />&ensp;{{ time }}</div>
    </header>
    <section class="main">
      <div class="mainLeft">
        <div class="ysyMonitor" v-for="item in ysyList" :key="item.id">
          <div class="button">
            <a-dropdown>
              <a-menu slot="overlay">
                <a-menu-item key="1"> <a-icon type="user" />1st menu item </a-menu-item>
                <a-menu-item key="2"> <a-icon type="user" />2nd menu item </a-menu-item>
                <a-menu-item key="3"> <a-icon type="user" />3rd item </a-menu-item>
              </a-menu>
              <a-button style="margin-left: 8px"> Button <a-icon type="down" /> </a-button>
            </a-dropdown>
          </div>
          <iframe
            :src="item.videoUrl"
            width="700"
            height="400"
            autoplay
          >
          </iframe>
        </div>
        <div class="ysyMonitor" style="width: 700px; height: 400px">

        </div>
      </div>
      <!-- mainRight -->
      <div v-show="false" class="">
        <div class="corner topleft"></div>
        <div class="corner topright"></div>
        <div class="corner bottomleft"></div>
        <div class="corner bottomright"></div>
        <div class="mainRightHeader">{{ parkInfo.parkName }}</div>
        <ul class="mainRightBody">
          <li>
            <div class="title"><img src="~@/assets/monitor/icon1.png" />停车场总车位</div>
            <div>
              <span class="number">{{ parkInfo.totalParkSpace }}</span
              >个
            </div>
          </li>
          <li>
            <div class="title"><img src="~@/assets/monitor/icon5.png" />剩余车位</div>
            <div>
              <span class="number">{{ parkInfo.remainingPark > 0 ? parkInfo.remainingPark : 0 }}</span
              >个
            </div>
          </li>
          <li>
            <div class="title"><img src="~@/assets/monitor/icon4.png" />场内临时车</div>
            <div>
              <span class="number">{{ parkInfo.parkSpace }}</span
              >个
            </div>
          </li>
          <li>
            <div class="title"><img src="~@/assets/monitor/icon2.png" />订单数量</div>
            <div>
              <span class="number">{{ parkInfo.countOrder }}</span
              >个
            </div>
          </li>
          <li>
            <div class="title"><img src="~@/assets/monitor/icon3.png" />临时车收费</div>
            <div>
              <span class="number">{{ parkInfo.todayOrderSum }}</span
              >元
            </div>
          </li>
        </ul>
      </div>
    </section>
    <!-- footer -->
    <footer v-show="false" class="">
      <div class="corner topleft"></div>
      <div class="corner topright"></div>
      <div class="corner bottomleft"></div>
      <div class="corner bottomright"></div>
      <div class="footerLeft">
        <img v-show="!currentImgSrc" src="~@/assets/loginimg.png" alt="" />
        <img v-show="currentImgSrc" :src="currentImgSrc" alt="" @error="imgError" />
      </div>
      <div class="footerRight">
        <a-tabs default-active-key="1" @change="tabsChange">
          <a-tab-pane key="1" tab="入场信息">
            <a-table
              :pagination="false"
              :columns="enterColumns"
              :data-source="parkCarEnterLogs"
              :scroll="{ y: 188 }"
              :customRow="rowClick"
              rowKey="id"
            >
            </a-table>
          </a-tab-pane>
          <a-tab-pane key="2" tab="出场信息">
            <a-table
              :pagination="false"
              :columns="outColumns"
              :data-source="parkCarOutLogs"
              :scroll="{ y: 188 }"
              :customRow="rowClick"
              rowKey="id"
            >
            </a-table>
          </a-tab-pane>
          <a-tab-pane key="3" tab="订单信息">
            <a-table
              :pagination="false"
              :columns="orderColumns"
              :data-source="parkOrderInfos"
              :scroll="{ y: 188 }"
              :customRow="rowClick"
              rowKey="id"
            >
            </a-table>
          </a-tab-pane>
          <a-button v-has="'admin:parkCode'" type="link" slot="tabBarExtraContent" @click="more"> 更多 </a-button>
        </a-tabs>
      </div>
    </footer>
    <div class="carModalWrap" v-show="orderInfos.length">
      <div class="carModal" v-for="(orderInfo, index) in orderInfos" :key="orderInfo.id">
        <div class="carModalHeader">
          {{ orderInfo.armName }}
          <a-icon type="close" @click="delOrder(index)" />
        </div>
        <div class="carModalMain">
          <div class="carModalLeft">
            <img :src="orderInfo.outImgPath" alt="" />
          </div>
          <div class="carModalRight">
            <div class="carModalRightHeader">
              <span>车牌号码：</span>
              <span class="carPlateNumber">{{ orderInfo.plateNo }}</span>
            </div>
            <ul class="carModalRightContent">
              <template v-if="orderInfo.carEnterId">
                <li>
                  <div class="label">车辆类型：</div>
                  <div>
                    <a-select
                      size="large"
                      style="width: 150px"
                      :default-value="orderInfo.carTypeId"
                      @change="carTypeChange"
                    >
                      <a-select-option v-for="carType in carTypes" :key="orderInfo.id + carType.id" :value="carType.id">
                        {{ carType.carTypeName }}</a-select-option
                      >
                    </a-select>
                  </div>
                </li>
                <li>
                  <div class="label">入场时间：</div>
                  <div>{{ orderInfo.enterTime }}</div>
                </li>
                <li>
                  <div class="label">停车时长：</div>
                  <div>
                    {{ orderInfo.days ? orderInfo.days + '天' : '' }}{{ orderInfo.hours ? orderInfo.hours + '小时' : ''
                    }}{{ orderInfo.minutes }}分
                  </div>
                </li>
                <li>
                  <div class="label">应付金额：</div>
                  <div class="needPayMoney">{{ orderInfo.chargeUnpaid / 100 }}元</div>
                </li>
              </template>
              <template v-else>
                <li class="noEnterRecord">
                  <img src="~@/assets/monitor/warning.png" alt="" />
                  <div>未找到入场信息</div>
                </li>
                <li>
                  <div class="label">输入缴费金额：</div>
                  <div class="inputPayMoney">
                    <a-input-number palceholder="请手动输入金额" v-model="orderInfo.chargeTotalFee" :min="0" />&ensp;元
                  </div>
                </li>
              </template>
              <li class="btn paidOpen" @click="open(orderInfo, index, false)">缴费放行</li>
              <li class="btn freeOpen" @click="open(orderInfo, index, true)">免费放行</li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
/**
 * 视频监控的websocket连接，以及相应的心跳检测重连机制
 */
function ScreenWs(parkArm, index, vueContext) {
  this.parkArm = parkArm //车道信息
  this.parkArmIndex = index //车道下标
  this.vueContext = vueContext //vue中的this
}
ScreenWs.prototype.init = function () {
  this.create()
  this.vueContext.WebSockets.push(this)
}
ScreenWs.prototype.create = function () {
  try {
    console.log('视频WS create')
    this.ws = new WebSocket(this.parkArm)
    this.initEventHandle()
  } catch (error) {
    console.log('视频WS create代码执行失败')
    this.reconnect()
  }
}
ScreenWs.prototype.timerClean = function () {
  this.timer && clearTimeout(this.timer)
  this.reconnectTimer && clearTimeout(this.reconnectTimer)
}
ScreenWs.prototype.initEventHandle = function () {
  console.log('视频WS事件绑定', this.parkArmIndex)
  this.ws.onopen = () => {
    console.log('视频ws open', this.parkArmIndex)
    this.vueContext.parkArmStateChange(this.parkArm, this.parkArmIndex, false)
  }
  this.ws.onerror = () => {
    console.log('视频wserror', this.parkArmIndex)
  }
  this.ws.onclose = (e) => {
    //ws因各种原因断开后重新创建ws连接
    console.log(e)
    if (this.forceClose) {
      console.log('强制关闭视频ws', this.parkArmIndex)
      this.timerClean()
    } else {
      console.log('视频ws close', this.parkArmIndex)
      this.vueContext.parkArmStateChange(this.parkArm, this.parkArmIndex, true)
      this.reconnect()
    }
  }
  this.ws.onmessage = (event) => {
    clearTimeout(this.timer)
    if (this.parkArm.noScreen) {
      console.log(this.parkArm.noScreen)
    }
    if (this.parkArm.noScreen === true) {
      this.vueContext.parkArmStateChange(this.parkArm, this.parkArmIndex, false)
    }
    this.timer = setTimeout(() => {
      //接收消息后10s内没有再次接收到消息时执行：当前车道没有画面，提示是否网络掉线等
      console.log('已经十秒钟没有哦接收到画面了', this.parkArmIndex)
      this.ws.close()
    }, 10000)
    let imgDom = document.getElementById('img' + this.parkArm.id)
    if (imgDom === null) {
      return
    }
    let reader = new FileReader()
    let that = this
    reader.onload = function (readerEvent) {
      if (readerEvent.target.readyState === FileReader.DONE) {
        imgDom.src = this.result
        if (that.vueContext.fullScreenIndex === that.parkArmIndex) {
          document.getElementById('bigImg' + that.vueContext.parkArms[that.vueContext.fullScreenIndex].id).src =
            this.result
        }
      }
    }
    reader.readAsDataURL(event.data)
  }
}
ScreenWs.prototype.reconnect = function () {
  console.log('视频WS reconert')
  if (this.lockReconnect) return
  this.lockReconnect = true
  //没连接上会一直重连，设置延迟避免请求过多
  this.timerClean()
  this.reconnectTimer = setTimeout(() => {
    console.log('重连定时器函数执行', this.parkArmIndex)
    this.create()
    this.lockReconnect = false
  }, 2000)
}
import Vue from 'vue'
import { getAction, postAction } from '@api/manage'
import { notification } from 'ant-design-vue'

export default {
  name: 'Monitor',
  data() {
    return {
      isNoEnterRecord: true, //标记是否没有入场记录
      carModalVisible: true, //是否显示车辆出场时的模态框
      timer: null, //右上角日期时间更新定时器
      time: new Date().toLocaleString(), //右上角的日期时间
      mac: null, //本机mac地址
      checkedScreenIndex: 0, //点击选中的视频画面的索引
      fullScreenIndex: -1, //全品的视频画面索引
      carNatures: ['临时车', '月租车', '储值车', '军警车', '白名单'], //车辆类型，用于页面下方图表显示
      parkArms: [], //车道信息
      parkInfo: {
        //页面右侧当前车场相关信息
        parkName: '',
        totalParkSpace: 0, //总车位
        remainingPark: 0, //剩余车位
        parkSpace: 0, //临时车
        countOrder: 0, //订单数
        todayOrderSum: 0, //总订单金额
      },
      payTypes: ['微信', '支付宝', '无感支付', '全免券', '储值卡', '线下缴费'],
      enterColumns: [
        //入场列表表头
        {
          title: '车牌号码',
          dataIndex: 'plateNo',
        },
        {
          title: '车辆类型', //0:临时车,1:月租车2:军警车
          dataIndex: 'carNature',
          key: 'carNature',
          customRender: (text) => this.carNatures[text],
        },
        {
          title: '入场地点',
          dataIndex: 'armName',
          key: 'armName',
        },
        {
          title: '停车状态',
          dataIndex: 'isOut',
          key: 'isOut',
          customRender(text) {
            return text === '0' ? '场内' : '出场'
          },
        },
        {
          title: '入场时间',
          dataIndex: 'carEnterTime',
          key: 'carEnterTime',
        },
      ],
      outColumns: [
        //出场列表表头
        {
          title: '车牌号码',
          dataIndex: 'plateNo',
          key: 'plateNo',
        },
        {
          title: '车辆类型',
          dataIndex: 'carNature',
          key: 'carNature',
          customRender: (text) => this.carNatures[text],
        },
        {
          title: '出口',
          dataIndex: 'armName',
          key: 'armName',
          customRender: (text) => text || '无',
        },
        {
          title: '出场时间',
          dataIndex: 'createTime',
          key: 'createTime',
        },
      ],
      orderColumns: [
        //订单列表表头,
        {
          title: '车牌号码',
          dataIndex: 'plateNo',
          key: 'plateNo',
        },
        {
          title: '订单费用(元)',
          dataIndex: 'chargePaid',
          key: 'chargePaid',
          customRender: (text) => (text / 100).toFixed(2),
        },
        {
          title: '缴费方式', //1微信，2支付宝,3无感支付,4全免券,5储值卡，6线下收费
          dataIndex: 'payType',
          key: 'payType',
          customRender: (text) => this.payTypes[text - 1],
        },
        {
          title: '缴费时间',
          dataIndex: 'createTime',
          key: 'createTime',
          ellipsis: true,
        },
      ],
      parkCarEnterLogs: [], //入场记录列表数据
      parkCarOutLogs: [], //出场记录列表数据
      parkOrderInfos: [], //订单列表数据
      WebSockets: [], //车道视频链接的websocket
      carTypes: [], //车辆类型下拉列表
      //当前ws推送的订单信息
      orderInfos: [],
      //当前标签页key值
      tabsActiveKey: 1,
      currentImgSrc: '', //列表左侧显示的图片路径
      keyUpTimer: null,
      serverWSTimer: null,
      serverWS: null,
      serverWsForceClose: false,
      ysyList: [],
    }
  },
  methods: {
    getYsyList() {
      getAction('/ysyDevice/ysyDevice/list', {}).then((res) => {
        if (res.success) {
          this.ysyList = res.result.records
        }
        if (res.code === 510) {
          this.$message.warning(res.message)
        }
      })
    },
    initKeyUpEnter() {
      var _this = this
      document.onkeydown = function () {
        if (_this.orderInfos.length !== 1) {
          return
        }
        let key = window.event.keyCode
        if (key === 13 || key === 32) {
          if (_this.keyUpTimer) {
            clearTimeout(_this.keyUpTimer)
          }
          _this.keyUpTimer = window.setTimeout(() => {
            let orderInfo = _this.orderInfos[0]
            _this.open(orderInfo, 0, false)
            clearTimeout(_this.keyUpTimer)
          }, 500)
        }
      }
    },
    imgError() {
      console.log('error')
      this.currentImgSrc = ''
    },
    rowClick(record) {
      let that = this
      return {
        on: {
          click() {
            that.currentImgSrc = record.imgPath
            console.log(that.currentImgSrc)
          },
        },
      }
    },
    serverWSCreate() {
      //与后台服务的ws连接
      //测试地址
      let wsUrl = 'ws://' + location.hostname + ':8094/park-single/websocket/' + this.mac
      //生产环境地址
      // let wsUrl = "ws://"+location.hostname+"/park-single/websocket/" + this.mac;
      let lockReconnect = false
      let reconnectTimer
      let that = this
      function create() {
        try {
          console.log('创建与服务端的连接')
          that.serverWS = new WebSocket(wsUrl)
          initEventHandle()
        } catch (error) {
          console.log('创建与服务端的连接代码异常')
          reconnect(wsUrl)
        }
      }
      let initEventHandle = () => {
        console.log('与服务端的ws事件绑定')
        that.serverWS.onopen = () => {
          console.log('与服务端的连接open')
          heartCheck.reset().start()
        }
        that.serverWS.onmessage = () => {
          console.log('与服务端的连接message')
          heartCheck.reset().start()
          if (event.data === '连接成功') {
            return
          }
          let data = JSON.parse(event.data)
          if (data.parkOrderInfo) {
            //有车辆出场
            data.parkOrderInfo.minutes = data.parkOrderInfo.chargeDuration % 60
            let hours = parseInt(data.parkOrderInfo.chargeDuration / 60)
            data.parkOrderInfo.hours = hours % 60
            data.parkOrderInfo.days = parseInt(hours / 24)
            let findIndex = this.orderInfos.findIndex((item) => {
              //避免同车道车辆重复显示
              return item.serialNo === data.parkOrderInfo.serialNo
            })
            if (findIndex !== -1) {
              this.$set(this.orderInfos, findIndex, data.parkOrderInfo)
            } else {
              this.orderInfos.push(data.parkOrderInfo)
            }
          } else if (data.parkOrderInfos) {
            //车场统计信息
            this.parkCarEnterLogs = data.parkCarEnterLogs
            this.parkCarOutLogs = data.parkCarOutLogs
            this.parkOrderInfos = data.parkOrderInfos
            Object.assign(this.parkInfo, data)
          } else if (data.successOrder) {
            let findIndex = this.orderInfos.findIndex((item) => {
              //避免同车道车辆重复显示
              return item.id === data.successOrder.id
            })
            that.delOrder(findIndex)
          }
        }
        that.serverWS.onclose = () => {
          console.log('与服务端的连接close')
          if (that.serverWsForceClose) {
            heartCheck.reset()
            return
          }
          reconnect()
        }
      }

      function reconnect() {
        console.log('与服务端的连接reconnect')
        console.log('lockReconnect:', lockReconnect)
        if (lockReconnect) return
        lockReconnect = true
        reconnectTimer && clearTimeout(reconnectTimer)
        reconnectTimer = setTimeout(() => {
          console.log('lockReconnect:', lockReconnect)
          create()
          lockReconnect = false
        }, 2000)
      }

      let heartCheck = {
        timeout: 10000,
        timeoutObj: null,
        serverTimeoutObj: null,
        reset: function () {
          console.log('与服务端的连接心跳reset执行')
          clearTimeout(this.timeoutObj)
          clearTimeout(this.serverTimeoutObj)
          return this
        },
        start: function () {
          console.log('与服务端的连接心跳start')
          let self = this
          this.timeoutObj = setTimeout(function () {
            console.log('与服务端的连接心跳timeoutobj处理函数执行')
            that.serverWS.send('还在么')
            self.serverTimeoutObj = setTimeout(() => {
              console.log('与服务端的连接心跳serverTimeoutObj处理函数执行')
              that.serverWS.close()
            }, self.timeout)
          }, this.timeout)
        },
      }
      create()
    },
    carTypeChange(value, option) {
      //车辆类型手动更改
      let findIndex = this.orderInfos.findIndex((item) => {
        return (item.id = option.key.replace(value, ''))
      })
      let newOrderInfo = Object.assign({}, this.orderInfos[findIndex])
      newOrderInfo.carTypeId = value
      this.$set(this.orderInfos, findIndex, newOrderInfo)
      postAction('/parking/parkCharge/parkChargeFee', newOrderInfo).then((res) => {
        if (res.success) {
          newOrderInfo.chargeTotalFee = res.result
          newOrderInfo.chargeUnpaid = res.result
          this.$set(this.orderInfos, findIndex, newOrderInfo)
        }
        this.$message[res.success ? 'success' : 'error'](res.message)
      })
    },
    delOrder(index) {
      //关闭显示当前的订单消息窗口
      this.orderInfos.splice(index, 1)
    },
    back() {
      //返回按钮事件
      this.exitFullScreen()
    },
    exitFullScreen() {
      //退出全屏
      if (!document.fullscreenElement) {
        if (this.$route.name === 'Monitor') {
          this.$router.back()
        }
        return
      }
      if (document.exitFullscreen) {
        document.exitFullscreen()
      } else if (document.msExitFullscreen) {
        document.msExitFullscreen()
      } else if (document.mozCancelFullScreen) {
        document.mozCancelFullScreen()
      } else if (document.webkitCancelFullScreen) {
        document.webkitCancelFullScreen()
      }
    },
    saveMacToStorage() {
      //将本机mac保存到storage中
      return new Promise((resolve) => {
        let LODOP = window.getLodop()
        LODOP.GET_SYSTEM_INFO('NetworkAdapter.1.PhysicalAddress')
        if (LODOP.CVERSION) {
          window.CLODOP.On_Return = function (TaskID, Value) {
            Vue.ls.set('mac', Value)
            resolve()
          }
        }
      })
    },
    getMacFromStorage() {
      //从storage获取mac赋值给data
      this.mac = Vue.ls.get('mac')
    },
    getData() {
      let params = {
        mac: this.mac,
      }
      getAction('/parking/parkArmInfo/getData', params).then((response) => {
        if (response.success) {
          console.log(response.result)
          let result = response.result
          // Object.assign(this.parkInfo, result);
          this.parkInfo.totalParkSpace = result.totalParkSpace //总车位
          ;(this.parkInfo.remainingPark = result.remainingPark), //剩余车位
            (this.parkInfo.parkSpace = result.parkSpace), //临时车
            (this.parkInfo.countOrder = result.countOrder), //订单数
            (this.parkInfo.todayOrderSum = result.todayOrderSum) //总订单金额
          this.parkInfo.parkName = result.parkName
          this.parkCarEnterLogs = result.parkCarEnterLogs
          this.parkCarOutLogs = result.parkCarOutLogs
          this.parkOrderInfos = result.parkOrderInfos
          if (result.parkArm.length > 4) {
            result.parkArm = result.parkArm.slice(0, 4)
          }
          result.parkArm.forEach((parkArm) => {
            parkArm.noScreen = true
          })
          this.parkArms = result.parkArm
          this.carTypes = result.carType
          this.$nextTick(() => {
            this.WebSockets = []
            this.parkArms.forEach((parkArm, index) => {
              // this.screenWSCreate(parkArm, index);

              new ScreenWs(parkArm, index, this).init()
            })
          })
        }
      })
    },
    timeInterval() {
      //启动日期刷新定时器
      this.timer = setInterval(() => {
        this.time = new Date().toLocaleString()
      }, 1000)
    },
    open(orderInfo, orderIndex, isFree) {
      //缴费放行、免费放行
      orderInfo = Object.assign({}, orderInfo)
      if (isFree) {
        orderInfo.chargeTotalFee = 0
      } else {
        //缴费放行
        if (!orderInfo.hasOwnProperty('carEnterId')) {
          //无入场记录
          orderInfo.chargeTotalFee *= 100
        }
      }
      orderInfo.chargeTotalFee += ''
      postAction('/sdk/ioUnfold', orderInfo).then((res) => {
        if (res.success) {
          this.delOrder(orderIndex)
        }
        //将message显示出来
        this.$message[res.success ? 'success' : 'error'](res.message)
      })
    },
    emergencyOpen(serialNo) {
      //应急开闸
      getAction('sdk/unfold', { serialNo }).then((res) => {
        this.$message[res.success ? 'success' : 'error'](res.message)
      })
    },
    tabsChange(key) {
      this.tabsActiveKey = key
    },
    more() {
      this.$router.push(
        [
          '/parking/parkCarEnterLog/parkCarEnterLogList',
          '/parking/parkCarOutLog/parkCarOutLogList',
          '/order/ParkOrderInfoList',
        ][this.tabsActiveKey - 1]
      )
    },
    wsDestroy() {
      console.log('destroy')
      this.WebSockets.forEach((item) => {
        item.forceClose = true
        item.timerClean()
        item.ws.close()
      })
      this.serverWsForceClose = true
      this.serverWS.close()
    },
    parkArmStateChange(parkArm, parkArmIndex, noScreen) {
      parkArm.noScreen = noScreen
      this.parkArms.splice(parkArmIndex, 1, Object.assign({}, parkArm))
    },
  },
  mounted() {
    //监听退出全屏事件（根据resize事件判断），调用this.back函数
    var that = this
    document.onfullscreenchange = () => {
      if (!document.fullscreenElement) {
        if (that.$route.name === 'Monitor') {
          that.wsDestroy()
          that.$router.back()
        }
      }
    }
    this.initKeyUpEnter()
  },
  created() {
    this.getMacFromStorage()
    this.getYsyList()
    if (this.mac) {
      this.getData()
    } else {
      this.saveMacToStorage()
        .then(() => {
          this.getMacFromStorage()
          this.getData()
        })
        .catch(() => {
          // notification.error({
          //   message: '错误提示',
          //   description: '没有找到Mac',
          //   duration: 4,
          // })
        })
    }
    this.timeInterval()
    this.serverWSCreate()
  },
}
</script>

<style lang="less">
.maintorPage {
  color: #83c3ff;
  padding: 17px 40px;
  background-color: #171e30;
  min-height: 100%;

  .header {
    height: 65px;
    background: url(~@assets/monitor/header.png) no-repeat center center;
    background-size: 50%;
    display: flex;
    justify-content: space-between;
    font-size: 16px;
    align-items: center;

    .back {
      cursor: pointer;
    }

    .time,
    .back {
      display: flex;
      align-items: center;
    }

    img {
      height: 24px;
      width: 24px;
    }
  }

  .main {
    display: flex;
    margin: 20px 0;
    // height: 614px;

    .monitorScreen:only-child {
      width: 100%;
      height: 100%;
    }

    .monitorScreen.length2 {
      height: 100%;
    }

    .mainLeft {
      // width: calc(80% - 20px);

      display: flex;
      justify-content: space-between;
      flex-wrap: wrap;
      margin-right: 20px;
      align-content: space-between;
      .ysyMonitor {
        position: relative;
        margin-bottom: 20px;
        .button {
          position: absolute;
          top: 8px;
          left: 120px;
        }
      }
    }

    .mainRight {
      width: 20%;
      height: 100%;
      background: linear-gradient(360deg, rgba(0, 19, 45, 0.2) 0%, rgba(0, 28, 66, 0) 100%);
      box-shadow: 0px 0px 54px 0px rgba(0, 14, 40, 0.5);
      border: 1px solid;
      position: relative;
    }

    .mainRightHeader {
      line-height: 60px;
      background-image: linear-gradient(96deg, #06286b, #000b20);
      font-size: 24px;
      color: #75bcff;
      text-align: center;
      font-weight: bold;
    }

    .mainRightBody {
      height: calc(100% - 60px);
      padding: 1px 10% 0;
      margin: 0;

      li:first-child {
        border: 0;
      }

      li {
        height: 20%;
        border-top: 1px solid #0d396a;
        list-style: none;
        color: #83c3ff;

        .title {
          font-size: 18px;
          display: flex;
          align-items: center;
          padding: 20px 0 12px;
        }

        img {
          margin-right: 11px;
        }

        .number {
          font-size: 27px;
          font-weight: bold;
          color: #1990ff;
          margin-left: 32px;
        }
      }
    }
  }

  .footer {
    display: flex;
    height: 314px;
    padding: 14px;
    justify-content: space-between;
    background-color: #072d69;
    border: 1px solid #1c69d3;
    position: relative;
    .ant-tabs-extra-content {
      line-height: normal;
      .ant-btn ant-btn-link {
        height: auto;
      }
    }
    .footerLeft {
      width: 25%;
      display: flex;
      justify-content: center;
      align-items: center;

      img {
        max-width: 98%;
        max-height: 98%;
        border-radius: 2px;
      }
    }

    .footerRight {
      width: 75%;
      padding-left: 40px;

      .ant-table {
        color: #fff;
      }

      .ant-tabs-bar {
        border-color: #1b68d2;
      }

      .ant-tabs-tab {
        color: #6799c8;
      }

      .ant-tabs-tab-active {
        color: #fff;
      }

      .ant-tabs {
        color: #fff;

        .ant-tabs-nav .ant-tabs-tab {
          padding-top: 0;
        }

        .ant-tabs-nav-container {
          margin-top: 0;
        }
      }

      .ant-table-thead > tr > th {
        background: linear-gradient(96deg, #082867 0%, #06286a 100%);
        color: #1990ff;
        font-size: 16px;
      }

      .ant-table-thead > tr > th,
      .ant-table-tbody > tr > td {
        padding: 13px;
        border: 0;
      }

      .ant-table-thead > tr.ant-table-row-hover:not(.ant-table-expanded-row):not(.ant-table-row-selected) > td,
      .ant-table-tbody > tr.ant-table-row-hover:not(.ant-table-expanded-row):not(.ant-table-row-selected) > td,
      .ant-table-thead > tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected) > td,
      .ant-table-tbody > tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected) > td {
        background-color: #162d5a;
      }
    }
  }

  .quadrangle {
    position: relative;
  }

  .ant-table-fixed-header > .ant-table-content > .ant-table-scroll > .ant-table-body,
  .ant-table-header,
  .ant-table-fixed-header > .ant-table-content > .ant-table-scroll > .ant-table-body {
    background-color: #072d69;
  }
}

.monitorScreen {
  width: 49%;
  height: 297px;
  background-color: #00112c;
  position: relative;
  border: 1px solid transparent;

  .monitorScreenHeader {
    line-height: 40px;
    display: flex;
    justify-content: space-between;
    background-color: rgba(0, 0, 0, 0.4);
    font-size: 12px;
    position: absolute;
    top: 0;
    width: 100%;
    z-index: 200;
  }

  .monitorScreenHeaderLeft {
    color: #fff;
    font-size: 16px;
  }

  .monitorScreenHeaderRight {
    display: flex;
    align-items: center;
    color: #35b37e;
  }

  .circle {
    width: 5px;
    height: 5px;
    background-color: #35b37e;
    border-radius: 50%;
    margin-right: 5px;
  }

  .car {
    margin: 0 13px;
  }

  .fullscreen,
  .restore {
    margin: 0 23px;
  }

  .emergency {
    position: absolute;
    right: 0;
    bottom: 45px;
    width: 106px;
    line-height: 36px;
    background-color: #1990ff;
    border-radius: 100px 0 0 100px;
    text-align: center;
    color: #fff;
    font-weight: bold;
    border: 0;
    cursor: pointer;
  }

  .screenImg {
    width: 100%;
    height: 100%;
    vertical-align: top;
  }

  .offline {
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
  }

  .corner {
    display: none;
  }
}
.error.monitorScreen {
  .monitorScreenHeaderRight {
    color: #fa6400;

    .circle {
      background-color: #fa6400;
    }
  }
}

.checked.monitorScreen {
  border-color: #0e5ac4;

  .corner {
    display: block;
  }
}

.monitorScreen:only-child {
  width: 100%;
}

.monitorScreen.dialog {
  height: 750px;

  .emergency {
    line-height: 76px;
    font-size: 30px;
    width: 200px;
  }
}

.monitorScreenDialog .ant-modal-body {
  padding: 0;
}

.monitorScreen.noVideo {
  display: flex;
  justify-content: center;
  align-items: center;
}

.carModalWrap {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(31, 31, 31, 0.7);
  align-items: center;
  z-index: 300;
  display: flex;
  justify-content: center;
}

.carModal {
  color: #fff;
  width: 49%;
  margin: 0 0.5%;
  background-color: #0046a6;
  border-radius: 6px;

  .carModalMain {
    display: flex;
    height: 580px;
  }

  .carModalLeft {
    width: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 10px;

    img {
      max-width: 100%;
    }
  }

  .carModalRight {
    width: 50%;
    padding: 0 2%;
  }

  .carModalRightHeader {
    background-color: #000c24;
    line-height: 88px;
    border-radius: 6px;
    font-size: 24px;
    display: flex;
    justify-content: center;
    width: 100%;
  }

  .carPlateNumber {
    color: #1990ff;
    font-weight: bold;
  }

  li {
    display: flex;
    font-size: 16px;
    line-height: 60px;
  }

  .label {
    font-size: 16px;
    color: #83c3ff;
    margin-right: 10px;
  }

  .needPayMoney {
    color: #fa6400;
    font-size: 20px;
    font-weight: bold;
  }

  .btn {
    margin: 25px 10% 0;
    font-size: 22px;
    word-spacing: 0.5px;
    line-height: 60px;
    border-radius: 6px;
    font-weight: bold;
    justify-content: center;
    cursor: pointer;
  }

  .paidOpen {
    background-color: #39bb71;
  }

  .freeOpen {
    background-color: #1990ff;
  }

  .noEnterRecord {
    color: #f7b500;
    font-size: 24px;
    font-weight: bold;
    justify-content: center;
    margin: 50px 0;

    img {
      margin-right: 10px;
    }
  }

  .carModalRightContent {
    margin: 20px 0 0;
    padding: 0;
  }

  .carModalHeader {
    display: flex;
    justify-content: space-between;
    padding: 10px 20px;
    width: 100%;
    font-size: 16px;
  }
}

.corner {
  position: absolute;
  padding: 20px;
  border: 3px solid #1968ff;
  z-index: 10;
}

.corner.topleft {
  border-width: 3px 0 0 3px;
  left: -3px;
  top: -3px;
}

.corner.topright {
  border-width: 3px 3px 0 0;
  right: -3px;
  top: -3px;
}

.corner.bottomleft {
  border-width: 0 0 3px 3px;
  bottom: -3px;
  left: -3px;
}

.corner.bottomright {
  border-width: 0 3px 3px 0;
  right: -3px;
  bottom: -3px;
}
@media screen and (max-device-width: 1440px) {
  .maintorPage {
    .main {
      .mainRightHeader,
      .carModalRightHeader,
      .noEnterRecord {
        font-size: 20px;
      }
    }
  }
}
@media screen and (max-device-width: 1080px) {
  .maintorPage {
    .main {
      .mainRightHeader,
      .carModalRightHeader,
      .noEnterRecord {
        font-size: 16px;
      }
    }
  }
}
</style>
